//
// Created by Zeppyrz on 2025/11/5.
//

#include "CommonTask.h"

#include <event2/bufferevent.h>
#include <event2/event.h>
#include <string.h>

#include <iostream>

#ifndef _WIN32
#  include <arpa/inet.h>
#endif

namespace ZeDisk {

static void _read_cb(bufferevent *, void *arg) {
  auto task = reinterpret_cast<CommonTask *>(arg);
  task->ReadCallback();
}
static void _write_cb(bufferevent *, void *arg) {
  auto task = reinterpret_cast<CommonTask *>(arg);
  task->WriteCallback();
}
static void _event_cb(bufferevent *bev, short what, void *arg) {
  auto task = reinterpret_cast<CommonTask *>(arg);
  task->EventCallback(what);
}

void CommonTask::ReadCallback() {
#ifdef DEBUG
  std::cout << "[DEBUG] CommonTask ReadCallback() " << std::endl;
#endif
  while (true) {  // 确保边缘触发时读取全部数据
    if (!is_recv_msg_) {
      int len = bufferevent_read(bev_, read_buffer_, sizeof(read_buffer_));
      if (len <= 0) return;
      HandleRawMessage(read_buffer_, len);
      continue;
    }
    // 1. 接收头部信息
    if (!msg_.data) {
      int header_size = sizeof(MessageHead);
      int len = bufferevent_read(bev_, (char *)&msg_.head, header_size);
      if (len != header_size) {
        std::cout << "[ERROR] Read header failed" << std::endl;
        return;
      }

      // 2. 验证消息头有效性
      if (msg_.head.type >= MSG_MAX_TYPE || msg_.head.size <= 0 ||
          msg_.head.size > MSG_MAX_SIZE) {
        std::cout << "[ERROR] Invalid message header" << std::endl;
        return;
      }
    }
    msg_.data = new char[msg_.head.size];
    int read_size = msg_.head.size - msg_.recved_size;
    if (read_size <= 0) {
      delete msg_.data;
      memset(msg_.data, 0, sizeof(msg_));
      return;
    }
    int len = bufferevent_read(bev_, msg_.data + msg_.recved_size, read_size);
    if (len <= 0) {
      return;
    }
    msg_.recved_size += len;
    if (msg_.recved_size == msg_.head.size) {
      // 处理消息
      HandleMessage(&msg_);

      delete[] msg_.data;
      memset(&msg_, 0, sizeof(msg_));
      return;
    }
  }
}

void CommonTask::BeginWrite() {
  if (!bev_) return;
  bufferevent_trigger(bev_, EV_WRITE, 0);
}

void CommonTask::WriteCallback() {}

void CommonTask::EventCallback(const short what) {
  // 退出要处理缓冲问题
  if (what & BEV_EVENT_ERROR || what & BEV_EVENT_TIMEOUT) {
    std::cout << "BEV_EVENT_ERROR && BEV_EVENT_TIMEOUT fd: " << sockfd()
              << std::endl;
    Stop();
    Completed() = true;
  } else if (what & BEV_EVENT_EOF) {
    std::cout << "[INFO] BEV_EVENT_EOF fd: " << sockfd() << std::endl;
    Stop();
    Completed() = true;
  } else if (what & BEV_EVENT_CONNECTED) {
    std::cout << "[INFO] Connect to " << server_ip() << ":" << port()
              << std::endl;
    // bufferevent_write(bev, "OK", 3);
    ConnectCallback();
  }
}

void CommonTask::ConnectCallback() {
#ifdef DEBUG
  std::cout << "[DEBUG] CommonTask ConnectCallback() " << std::endl;
#endif
}

void CommonTask::HandleMessage(const Message *msg) {
#ifdef DEBUG
  std::cout << "[DEBUG] Receive message type: " << msg->head.type
            << " message size: " << msg->head.size << std::endl;
#endif
}

void CommonTask::HandleRawMessage(void *data, int size) {
#ifdef DEBUG
  std::cout << "[DEBUG] Receive raw message size: " << size << std::endl;
#endif
}

bool CommonTask::WriteMessage(const Message *msg) {
  if (!msg || !msg->data || msg->head.size <= 0) return false;
  // 写入消息头
  int re = bufferevent_write(bev_, &msg->head, sizeof(MessageHead));
  if (re) return false;
  re = bufferevent_write(bev_, msg->data, msg->head.size);
  if (re) return false;
  return true;
}

bool CommonTask::WriteRawMessage(const void *data, int size) {
  if (!data || size <= 0) return false;
  int re = bufferevent_write(bev_, data, size);
  if (re) return false;
  return true;
}

bool CommonTask::Init() {
  // 建立连接, -1 自动创建socket
  // 如果是服务端 sockfd > 0 则使用已有的socket
  // 否则创建socket
  auto commSock = this->sockfd();
  if (commSock <= 0) commSock = -1;
  bev_ = bufferevent_socket_new(base_, commSock, BEV_OPT_CLOSE_ON_FREE);
  if (!bev_) {
    std::cout << "[ERROR] bufferevent_socket_new failed" << std::endl;
    return false;
  }

  // 设置回调函数
  bufferevent_setcb(bev_, _read_cb, _write_cb, _event_cb, this);
  bufferevent_enable(bev_, EV_READ | EV_WRITE);

  // 设置超时时间
  timeval delay = {10, 0};
  bufferevent_set_timeouts(bev_, &delay, &delay);

  // 如果是服务端则不需要连接
  if (server_ip_.empty()) return true;
  sockaddr_in sin = {0};
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = inet_addr(server_ip_.c_str());
  sin.sin_port = htons(port_);
  int re = bufferevent_socket_connect(bev_, reinterpret_cast<sockaddr *>(&sin),
                                      sizeof(sin));
  if (re) return false;

  return true;
}

bool CommonTask::Stop() {
  if (bev_) {
    bufferevent_free(bev_);
    bev_ = nullptr;
  }

  if (msg_.data) {
    delete[] msg_.data;
    msg_.data = nullptr;
  }

  memset(&msg_, 0, sizeof(msg_));
  return true;
}

}  // namespace ZeDisk